﻿using System;
using System.Collections.Generic;
using EnCor.Config;
using EnCor.ModuleLoader;

namespace EnCor
{
    public class Module
    {
        private ModuleInfo _ModuleInfo;
        private readonly List<BizService> _Services = new List<BizService>();
        private IModuleContext _ModuleContext;
        private ModuleStatus _Status = ModuleStatus.New;

        #region Public Members
        public void DoInit(IModuleContext moduleContext)
        {
            if (_Status!= ModuleStatus.New)
            {
                throw new ModuleStatusException("Module has completed initializing.");
            }
            _ModuleContext = moduleContext;
            Init(moduleContext.Config);
            _Status = ModuleStatus.Initialized;
        }

        public void DoStart()
        {
            if ( _Status != ModuleStatus.Initialized)
            {
                throw new ModuleStatusException("Module has wrong status to invoke DoStart.");
            }
            Start();
            _Status = ModuleStatus.Start;
        }

        public void DoStop()
        {
            if (_Status != ModuleStatus.Start)
            {
                throw new ModuleStatusException("Module has wrong status to invoke DoStop.");
            }
            Stop();
            _Status = ModuleStatus.Stop;
        }

        #endregion

        protected void RegisterBizService(BizService service, params Type[] interfaces)
        {
            _ModuleContext.RegisterBizService(service, interfaces);

            _Services.Add(service);
        }

        public IModuleInfo ModuleInfo
        {
            get
            {
                return _ModuleInfo;
            }
        }

        #region Portected Members
        protected void StartServices()
        {
            foreach ( BizService service in _Services)
            {
                service.Start();
            }
        }

        protected void StopServices()
        {
            foreach (BizService service in _Services)
            {
                service.Stop();
            }
        }

        protected BizService BuildService(ServiceConfig serviceConfig)
        {
            try
            {
                BizService service = _ModuleContext.BuildService(serviceConfig, _ModuleContext.Config.Name);
                if ( service == null)
                {
                    throw new EnCorException(string.Format("Service build fail, service config: {0}", serviceConfig));
                }

                return service;
            }
            catch (ServiceBuildException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ServiceBuildException("Error when build BizService.", ex);
            }
        }

        #endregion

        #region Virtual Members

        protected virtual void Init(ModuleConfig config)
        {
            foreach (ServiceConfig serviceConfig in config.Services)
            {
                BizService service = BuildService(serviceConfig);

                RegisterBizService(service, serviceConfig.Interfaces);
            }
        }

        protected virtual void Start()
        {
            StartServices();
        }

        protected virtual void Stop()
        {
            StopServices();
        }


        #endregion
    }
}
